/**
 * 阿里云智能体应用流式输出工具类
 * 基于阿里云DashScope API实现智能体应用的流式调用
 */
class DashScopeStreamClient {
  constructor(apiKey, appId) {
    this.apiKey = apiKey;
    this.appId = appId;
    this.baseURL = 'https://dashscope.aliyuncs.com/api/v1/apps';
  }

  /**
   * 调用智能体应用并获取流式输出
   * @param {string} prompt - 用户输入的提示词
   * @param {Object} options - 可选参数
   * @param {Function} onMessage - 接收到消息时的回调函数
   * @param {Function} onComplete - 完成时的回调函数
   * @param {Function} onError - 错误时的回调函数
   * @returns {Promise} - 返回一个Promise对象
   */
  async streamCall(prompt, options = {}, onMessage, onComplete, onError) {
    const {
      incremental_output = true,
      debug = {}
    } = options;

    const requestData = {
      input: {
        prompt: prompt
      },
      parameters: {
        incremental_output: incremental_output
      },
      debug: debug
    };

    try {
      const response = await fetch(`${this.baseURL}/${this.appId}/completion`, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${this.apiKey}`,
          'Content-Type': 'application/json',
          'X-DashScope-SSE': 'enable'
        },
        body: JSON.stringify(requestData)
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      let buffer = '';
      let fullText = '';
      let sessionId = null;
      let request_id = null;
      let usage = null;

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;

        buffer += decoder.decode(value, { stream: true });
        const lines = buffer.split('\n');
        buffer = lines.pop(); // 保留最后一个可能不完整的行

        for (const line of lines) {
          if (line.trim() === '') continue;
          
          // 解析SSE格式
          if (line.startsWith('id:')) {
            // 可以在这里处理id
          } else if (line.startsWith('event:')) {
            // 可以在这里处理event
          } else if (line.startsWith(':HTTP_STATUS/200')) {
            // 状态行，可以忽略
          } else if (line.startsWith('data:')) {
            try {
              const dataStr = line.substring(5).trim();
              const data = JSON.parse(dataStr);
              
              if (data.output) {
                const { text, finish_reason, session_id } = data.output;
                
                if (session_id) sessionId = session_id;
                if (data.request_id) request_id = data.request_id;
                if (data.usage) usage = data.usage;
                
                // 如果是增量输出，只返回新增的文本
                if (incremental_output && text) {
                  fullText += text;
                  if (onMessage) onMessage(text, data);
                } else if (!incremental_output && text) {
                  fullText = text;
                  if (onMessage) onMessage(text, data);
                }
                
                // 检查是否完成
                if (finish_reason === 'stop' || finish_reason === null) {
                  if (onComplete) onComplete(fullText, { sessionId, request_id, usage });
                  return;
                }
              }
            } catch (error) {
              console.error('解析SSE数据出错:', error);
              if (onError) onError(error);
            }
          }
        }
      }

      // 处理缓冲区中剩余的数据
      if (buffer.trim() !== '') {
        try {
          const dataStr = buffer.startsWith('data:') ? buffer.substring(5).trim() : buffer;
          const data = JSON.parse(dataStr);
          if (data.output && data.output.text) {
            fullText += data.output.text;
          }
        } catch (error) {
          console.error('解析剩余缓冲区数据出错:', error);
        }
      }

      if (onComplete) onComplete(fullText, { sessionId, request_id, usage });
    } catch (error) {
      console.error('请求出错:', error);
      if (onError) onError(error);
      throw error;
    }
  }

  /**
   * 使用Promise包装的流式调用方法
   * @param {string} prompt - 用户输入的提示词
   * @param {Object} options - 可选参数
   * @returns {Promise} - 返回一个Promise，resolve为完整文本和元数据
   */
  async streamCallPromise(prompt, options = {}) {
    return new Promise((resolve, reject) => {
      let fullText = '';
      const metadata = {};
      
      this.streamCall(
        prompt,
        options,
        (text, data) => {
          // 每次接收到消息时的处理
          fullText += text;
        },
        (text, meta) => {
          // 完成时的处理
          resolve({ text: fullText, metadata: meta });
        },
        (error) => {
          // 错误时的处理
          reject(error);
        }
      );
    });
  }

  /**
   * 创建一个可取消的流式调用
   * @param {string} prompt - 用户输入的提示词
   * @param {Object} options - 可选参数
   * @param {Function} onMessage - 接收到消息时的回调函数
   * @param {Function} onComplete - 完成时的回调函数
   * @param {Function} onError - 错误时的回调函数
   * @returns {Object} - 返回一个包含cancel方法的对象
   */
  createCancellableStreamCall(prompt, options = {}, onMessage, onComplete, onError) {
    let cancelled = false;
    let controller = new AbortController();

    const execute = async () => {
      const {
        incremental_output = true,
        debug = {}
      } = options;

      const requestData = {
        input: {
          prompt: prompt
        },
        parameters: {
          incremental_output: incremental_output
        },
        debug: debug
      };

      try {
        const response = await fetch(`${this.baseURL}/${this.appId}/completion`, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${this.apiKey}`,
            'Content-Type': 'application/json',
            'X-DashScope-SSE': 'enable'
          },
          body: JSON.stringify(requestData),
          signal: controller.signal
        });

        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }

        const reader = response.body.getReader();
        const decoder = new TextDecoder();
        let buffer = '';
        let fullText = '';
        let sessionId = null;
        let request_id = null;
        let usage = null;

        while (!cancelled) {
          const { done, value } = await reader.read();
          if (done) break;

          buffer += decoder.decode(value, { stream: true });
          const lines = buffer.split('\n');
          buffer = lines.pop(); // 保留最后一个可能不完整的行

          for (const line of lines) {
            if (line.trim() === '') continue;
            
            // 解析SSE格式
            if (line.startsWith('id:')) {
              // 可以在这里处理id
            } else if (line.startsWith('event:')) {
              // 可以在这里处理event
            } else if (line.startsWith(':HTTP_STATUS/200')) {
              // 状态行，可以忽略
            } else if (line.startsWith('data:')) {
              try {
                const dataStr = line.substring(5).trim();
                const data = JSON.parse(dataStr);
                
                if (data.output) {
                  const { text, finish_reason, session_id } = data.output;
                  
                  if (session_id) sessionId = session_id;
                  if (data.request_id) request_id = data.request_id;
                  if (data.usage) usage = data.usage;
                  
                  // 如果是增量输出，只返回新增的文本
                  if (incremental_output && text) {
                    fullText += text;
                    if (onMessage) onMessage(text, data);
                  } else if (!incremental_output && text) {
                    fullText = text;
                    if (onMessage) onMessage(text, data);
                  }
                  
                  // 检查是否完成
                if (finish_reason === 'stop' || finish_reason === null) {
                  if (onComplete) onComplete(fullText, { sessionId, request_id, usage });
                  return;
                }
                }
              } catch (error) {
                console.error('解析SSE数据出错:', error);
                if (onError) onError(error);
              }
            }
          }
        }

        // 处理缓冲区中剩余的数据
        if (buffer.trim() !== '') {
          try {
            const dataStr = buffer.startsWith('data:') ? buffer.substring(5).trim() : buffer;
            const data = JSON.parse(dataStr);
            if (data.output && data.output.text) {
              fullText += data.output.text;
            }
          } catch (error) {
            console.error('解析剩余缓冲区数据出错:', error);
          }
        }

        if (cancelled) {
          console.log('请求已取消');
        } else if (onComplete) {
          onComplete(fullText, { sessionId, request_id, usage });
        }
      } catch (error) {
        if (error.name === 'AbortError') {
          console.log('请求已取消');
        } else {
          console.error('请求出错:', error);
          if (onError) onError(error);
        }
      }
    };

    execute();

    return {
      cancel: () => {
        cancelled = true;
        controller.abort();
      }
    };
  }
}

export default DashScopeStreamClient;